// Copyright 2007 Google Inc. All Rights Reserved.

package com.google.jessewilson.codesearch.io.jdom;

import org.jdom.Document;
import org.jdom.Element;
import org.jdom.JDOMException;
import org.jdom.input.SAXBuilder;
import org.jdom.output.Format;
import org.jdom.output.XMLOutputter;

import java.io.IOException;
import java.io.StringReader;
import java.util.logging.Level;
import java.util.logging.Logger;

/**
 * Convert between XML and Objects. 
 *
 * @author jessewilson
 */
public class Formatter<T> {

  private final Externalizer<T> externalizer;
  private final String baseElementName;

  public Formatter(Externalizer<T> externalizer, String baseElementName) {
    this.externalizer = externalizer;
    this.baseElementName = baseElementName;
  }

  public String toXml(T object) {
    assert(object != null);

    Element element = new Element(baseElementName);
    externalizer.writeExternal(element, object);
    Document document = new Document(element);
    Format prettyFormat = Format.getPrettyFormat();
    prettyFormat.setLineSeparator("\n");
    return new XMLOutputter(prettyFormat).outputString(document);
  }

  public T fromXml(String xml) {
    if (xml == null) {
      return null;
    }

    try {
      Document document = new SAXBuilder().build(new StringReader(xml));
      Element element = document.getRootElement();
      return externalizer.readExternal(element);
    } catch(JDOMException e) {
      Logger.getLogger(Formatter.class.getName())
          .log(Level.WARNING, "failed to read settings from XML, \"" + xml + "\"", e);
      return null;
    } catch(IOException e) {
      Logger.getLogger(Formatter.class.getName())
          .log(Level.WARNING, "failed to read settings from XML, \"" + xml + "\"", e);
      return null;
    }
  }
}
